Skip to main content

Laravel 加载之 bootstrap

简介

此章,主要讲的内容是 $this->bootstrap();Laravel 中的配置错误处理、配置日志记录、 检测应用环境 以及执行其他需要完成的任务 。

bootstrap 引导其实质是将下面的类中的 bootstrap 方法都执行一遍

protected $bootstrappers = [
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
\Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
\Illuminate\Foundation\Bootstrap\HandleExceptions::class,
\Illuminate\Foundation\Bootstrap\RegisterFacades::class,
\Illuminate\Foundation\Bootstrap\RegisterProviders::class,
\Illuminate\Foundation\Bootstrap\BootProviders::class,
];

看一下 handle 方法

public function handle($request)
{
try {
$request->enableHttpMethodParameterOverride();

$response = $this->sendRequestThroughRouter($request); // 重点这一行
} catch (Exception $e) {
$this->reportException($e);

$response = $this->renderException($request, $e);
} catch (Throwable $e) {
$this->reportException($e = new FatalThrowableError($e));

$response = $this->renderException($request, $e);
}

$this->app['events']->dispatch(
new Events\RequestHandled($request, $response)
);

return $response;
}

代码中标注的重点的一行 $response = $this->sendRequestThroughRouter($request); 就是这个 handle 方法核心内容了。

我们继续看 sendRequestThroughRouter 方法

protected function sendRequestThroughRouter($request)
{
$this->app->instance('request', $request);

Facade::clearResolvedInstance('request');

$this->bootstrap(); // 这就是这一章要讲的东西了

return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
}

代码中标注的 $this->bootstrap(); 就是 Laravel 引导配置加载的开始了,具体干了哪些工作呢:

  • 加载 .env 文件,将配置加载到内存中
  • 加载 config 目录下的所有配置文件
  • 修改系统默认异常处理函数(如语法错误等),将其替代为 Laravel 的异常处理。这就是为什么在开发 Laravel 应用时,语法出现错误,而报错信息已一种非常好看的界面显示的缘故
  • 注册 Facades ,将 Laravel 内的 Facades 类中的静态属性 $app 赋值为 服务容器
  • 注册服务提供者,区分即时实例化和延时实例化,即时的不需要标识别名,而延时的需要标识别名,主要对 config/app.phpproviders 键对应值(服务器提供者类全名)进行分类
  • 执行服务提供者的 boot 方法,其中路由文件加载和读取,就是在此步骤进行的

下面我们看一下 $this->bootstrap();

public function bootstrap()
{
if (! $this->app->hasBeenBootstrapped()) {
$this->app->bootstrapWith($this->bootstrappers());
}
}

这段代码是指,有没有进行过引导呀,有的话,不进入引导程序,没有则进入

下面我们看一下进入引导的,先看 $this->bootstrappers()

protected function bootstrappers()
{
return $this->bootstrappers;
}

这段就是返回了 bootstrappers 属性,它就是前言中展示的数组

下面我们看一下容器方法 bootstrapWith

public function bootstrapWith(array $bootstrappers)
{
$this->hasBeenBootstrapped = true;

foreach ($bootstrappers as $bootstrapper) {
$this['events']->fire('bootstrapping: '.$bootstrapper, [$this]);

$this->make($bootstrapper)->bootstrap($this); // 核心在这

$this['events']->fire('bootstrapped: '.$bootstrapper, [$this]);
}
}

上面核心代码,就是遍历 $bootstrapper 数组,将里面的类实例化后,执行实例化后的 bootstrap 方法,将容器作为参数传入。

这一章,讲到这里,下一章我们看一下 $bootstrappers 数组的第一个值(类全名)的引导(即加载 .env

protected $bootstrappers = [
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class, // 下一章看这个哦
\Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
\Illuminate\Foundation\Bootstrap\HandleExceptions::class,
\Illuminate\Foundation\Bootstrap\RegisterFacades::class,
\Illuminate\Foundation\Bootstrap\RegisterProviders::class,
\Illuminate\Foundation\Bootstrap\BootProviders::class,
];